﻿using System;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.ComponentModel.Composition.Hosting;
using Moq;
using WordNet.Core;
using WordNet.Core.DataContract;
using WordNet.Core.ElementContracts;
using UnitTestDataProvider.TestClasses;
using DataFileProvider;

namespace UnitTestDataProvider
{
    [TestClass]
    public class SynsetMapperUnitTest
    {
        [ClassInitialize]
        public static void ClassInit(TestContext context)
        {
            WNDictionary.Container = MEFLoader.Load();
        }

        [TestMethod]
        public void SynsetMapperGetALLTest()
        {
            // get ref to ISynset content type
            IContentType<ISynset> content = ContentType<ISynset>.GetDataContentType(POS.NOUN);
            // get ref to test parser
            var testParser = content.DataType.GetParser() as TestParserBase;
            testParser.Reset();

            // mock data provider
            Mock<IDataProvider<ISynset>> dataProviderMock = new Mock<IDataProvider<ISynset>>();
            dataProviderMock.Setup(dp => dp.IsOpen).Returns(false);
            dataProviderMock.Setup(dp => dp.Open()).Verifiable("Open was not called");

            // mock data source        
            Mock<IDataSource> dataSourceMock = new Mock<IDataSource>();
            dataProviderMock.Setup(dp => dp.GetSourceForContentType(content))
                .Returns(dataSourceMock.Object);

            // test AllLines
            string[] lines = new string[] { "one", "two", "three" };
            dataSourceMock.Setup(ds => ds.AllLines()).Returns(lines);

            SynsetMapper synsetMapperTest = new SynsetMapper(dataProviderMock.Object);
            int cnt = 0;
            foreach (var item in synsetMapperTest.GetAll(POS.NOUN))
            {
                Assert.AreEqual(lines[cnt++], item.Gloss);
            }
            dataProviderMock.Verify();
            Assert.IsTrue(testParser.Verify());
        }
       
        [TestMethod]
        public void SynsetMapperGetByKeyTest()
        {
            // synset id param
            ISynsetID synsetID = new SynsetID(11111, POS.NOUN);

            // get ref to ISynset content type
            IContentType<ISynset> content = ContentType<ISynset>
                .GetDataContentType(synsetID.PartOfSpeech);
            // get ref to test parser
            var testParser = content.DataType.GetParser() as TestParserBase;
            testParser.Reset();

            // mock data provider
            Mock<IDataProvider<ISynset>> dataProviderMock = new Mock<IDataProvider<ISynset>>();
            // test IsOpen
            dataProviderMock.Setup(dp => dp.IsOpen).Returns(false);
            // test Open
            dataProviderMock.Setup(dp => dp.Open()).Verifiable("Open was not called");

            // mock data source
            Mock<IDataSource> dataSourceMock = new Mock<IDataSource>();
            dataProviderMock.Setup(dp => dp.GetSourceForContentType(content))
                .Returns(dataSourceMock.Object).Verifiable("get data source");

            // test ReadLine
            int offset = synsetID.Offset;
            dataSourceMock.Setup(ds => ds.ReadLine(offset)).Returns("test");

            // run test
            SynsetMapper synsetMapperTest = new SynsetMapper(dataProviderMock.Object);
            var result = synsetMapperTest.GetByKey(synsetID);

            dataProviderMock.Verify();
            Assert.AreEqual("test", result.Gloss);
            Assert.IsTrue(testParser.Verify());

        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void GetByKeyThrowsErrorWhenNullParameter()
        {
            // mock data provider
            Mock<IDataProvider<ISynset>> dataProviderMock = new Mock<IDataProvider<ISynset>>();
            SynsetMapper synsetMapperTest = new SynsetMapper(dataProviderMock.Object);
            synsetMapperTest.GetByKey(null);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void GetByKeyThrowsErrorWhenWrongTypeParameter()
        {
            // mock data provider
            Mock<IDataProvider<ISynset>> dataProviderMock = new Mock<IDataProvider<ISynset>>();
            SynsetMapper synsetMapperTest = new SynsetMapper(dataProviderMock.Object);
            synsetMapperTest.GetByKey(new Object());
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void GetAllThrowsErrorWhenNullParameter()
        {
            // mock data provider
            Mock<IDataProvider<ISynset>> dataProviderMock = new Mock<IDataProvider<ISynset>>();
            SynsetMapper synsetMapperTest = new SynsetMapper(dataProviderMock.Object);
            synsetMapperTest.GetAll(null).ToArray();
        }


    }
}
